use std::fs::File;
use std::sync::{Arc};
use serde_derive::{Serialize, Deserialize};
use std::env;
use crate::core::plog;
use crate::core::stat::Status;

const CONF_FILE : &str = "pkp.json";

#[derive(Debug, Serialize, Deserialize)]
pub struct Conf {
    pub addr : String, //监听地址
    pub port : u32, //运行端口
    pub brokers : Vec<String>, //代理的broker地址
    pub rewrite : u32, //写入kafka重写次数,限制不超过3次
    pub timeout : u64, //每次写入的超时时间,单位秒
    pub stype : String, //每次写入的超时时间,单位秒
    pub log   : String, //log path
    pub log_lvl : String, //日志等级 
    pub stat_count : u64, //kafka的状态收集数据间隔
}

impl std::fmt::Display for Conf {
    fn fmt(&self,f : &mut std::fmt::Formatter ) -> std::fmt::Result {
        write!( f,
                "the proxy config file :  
                {{
                    addr    : {:?},
                    port    : {:?},
                    brokers : {:?},
                    rewrite : {:?},
                    timeout : {:?},
                    stype   : {:?},
                    log     : {:?},
                    log_lvl : {:?},
                    stat_cnt: {:?},
                }} \n",
                self.addr,self.port,self.brokers,self.rewrite,self.timeout,self.stype,self.log,self.log_lvl,self.stat_count
        )
    }
}

impl Conf {
    
    pub fn init_conf() -> Result<&'static Conf,String> {
        let mut conf_file : String = CONF_FILE.to_owned();
        let mut show_status : bool = false;
        let mut status_addr : String = String::from("");
        for argument in env::args() {
            let item : Vec<&str> = argument.split("=").collect();
            match item.get(0) {
                //帮助
                Some(&"-h") => {
                    Conf::show_help();
                    std::process::exit(0);
                },
                //显示服务运行状态
                Some(&"-s") => {
                    show_status = true;
                    match item.get(1){
                        Some(addr) =>{
                            status_addr = addr.to_string();
                        },
                        None => {},
                    }
                },
                //寻找自定义配置文件地址
                Some(&"-c") => {
                    match item.get(1){
                        Some(config) =>{
                            conf_file = config.to_string();
                        },
                        None => continue,
                    }
                },
                _ => continue,
            }
        }
        //初始化配置
        let c = Conf::get_config(Some(conf_file.as_str()));
        //配置日志
        plog::init_with_config(&c);
        //执行状态查询
        if show_status == true {
            Conf::get_running_status(status_addr);
            std::process::exit(0);
        }

        Ok(c)
    }

    pub fn get_config(conf_file : Option<&str>) -> &'static Conf {
        static mut CONF : Option<Arc<Conf>> = None;
        unsafe {
            CONF.get_or_insert_with(||{
                let file_name = conf_file.unwrap();
                let f = match File::open(file_name) {
                    Ok(file) => file,
                    Err(_) => {
                        eprintln!("the config file : {} can not found ~",file_name);
                        std::process::exit(0);
                    },
                };
                let conf = match serde_json::from_reader(f) {
                    Ok(config) => config,
                    Err(_) => {
                        eprintln!("the json config in file {}  is not correct，please check again ~",file_name);
                        std::process::exit(0);
                    },
                };
                Arc::new(conf)
            });
            CONF.as_ref().unwrap()
        }
    }

    pub fn get_running_status(addr : String){
        Status::get_running_status(addr);
    }

    pub fn show_help() {
        println!("
        the useage for pkp (kafka proxy for php):
            -h , for help.
            -c=config_file , read config from config_file.
            -s , show the status for the running service (service addr and port from the config file).
                 (-s=127.0.0.1:6029, service addr and port from the param).
            * you must set every config item for the config json.
            * stat_count item : each topic produce count will upgrade to the status service 
              while bigger than stat_count,and then produce count in the thread will to zero.
            * default log level is info. (error, warn, info, trace, debug)
            * default server protocol is TCP.
        ");
    }

}
